package com.qudian.pay.schedule.redis;

import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisPubSub;
import redis.clients.util.Pool;

/**
 * @Description: Jedis连接池实现
 * @ClassName: JedisTool
 * @author gaoxiang
 * @date 2016年5月16日 下午7:35:02
 */
public class JedisTool {
	
	private Logger logger = LoggerFactory.getLogger(JedisTool.class);
	
	private Pool<Jedis> pool = null;
	
	private String ipAddr;
	
	private String port;
	
	private String password;
	
	private int timeout = 3000;
	
	private int maxIdle = 5;
	
	public Pool<Jedis> getTool() {
		if (pool == null) {
			JedisPoolConfig config = new JedisPoolConfig();
			//控制一个pool可分配多少个jedis实例，通过pool.getResource()来获取
			config.setMaxTotal(20);
			//控制一个pool最多有多少个状态为idle(空闲的)的jedis实例
			config.setMaxIdle(maxIdle);
			//表示当borrow(引入)一个jedis实例时，最大的等待时间，如果超过等待时间，则直接抛出JedisConnectionException
			config.setMaxWaitMillis(100 * 1000);
			//在borrow一个jedis实例时，是否提前进行validate操作；如果为true，则得到的jedis实例均是可用的
			config.setTestOnBorrow(true);
			int portExe = StringUtils.isBlank(port) ? 6379 : Integer.parseInt(port);
			if (StringUtils.isBlank(password)) {
				pool = new JedisPool(config, ipAddr, portExe, timeout);
			} else {
				pool = new JedisPool(config, ipAddr, portExe, timeout, password);
			}
		}
		return pool;
	}
	
	/**
	 * @Description: 获取值
	 * @param key
	 * @return String 返回类型
	 * @author gaoxiang
	 * @date 2016年5月17日 下午5:22:51
	 */
	public String getValue(String key) {
		Jedis jedis = null;
		try {
			jedis = getTool().getResource();
			return jedis.get(key);
		} catch (Throwable t) {
			logger.error("Jedis getValue(String key) error!", t);
		} finally {
			if(jedis!=null) jedis.close();
		}
		return null;
	}
	
	/**
	 * @Description: 获取生存时间
	 * @param key
	 * @return long 返回类型
	 * @author gaoxiang
	 * @date 2016年5月17日 下午5:22:37
	 */
	public long ttl(String key) {
		Jedis jedis = null;
		try {
			jedis = getTool().getResource();
			return jedis.ttl(key).longValue();
		} catch (Throwable t) {
			logger.error("Jedis ttl(key) error!", t);
		} finally {
			if(jedis!=null) jedis.close();
		}
		return 0L;
	}
	
	/**
	 * @Description: 设值
	 * @param key
	 * @param value
	 * @return void 返回类型
	 * @author gaoxiang
	 * @date 2016年5月17日 下午5:22:26
	 */
	public void setValue(String key, String value) {
		Jedis jedis = null;
		try {
			jedis = getTool().getResource();
			jedis.set(key, value);
		} catch (Throwable t) {
			logger.error("Jedis setValue(String key, String value) error!", t);
		} finally {
			if(jedis!=null) jedis.close();
		}
	}
	
	/**
	 * @Description: 存储数据到缓存中，并制定过期时间和当Key存在时是否覆盖
	 * @param key
	 * @param value
	 * @param nxxx 值只能取NX或者XX，如果取NX，则只有当key不存在是才进行set，如果取XX，则只有当key已经存在时才进行set
	 * @param expx 值只能取EX或者PX，代表数据过期时间的单位，EX代表秒，PX代表毫秒
	 * @param time 过期时间，单位是expx所代表的单位
	 * @return void 返回类型
	 * @author gaoxiang
	 * @date 2016年5月17日 下午5:11:18
	 */
	public void setValue(String key, String value, String nxxx, String expx, int time) {
		Jedis jedis = null;
		try {
			jedis = getTool().getResource();
			jedis.set(key, value, nxxx, expx, time);
		} catch (Throwable t) {
			logger.error("Jedis setValue(String key, String value, String nxxx, String expx, int time) error!", t);
		} finally {
			if(jedis!=null) jedis.close();
		}
	}
	
	/**
	 * @Description: 如果不存在则设值，否则返回
	 * @param key
	 * @param value
	 * @return void 返回类型
	 * @author gaoxiang
	 * @date 2016年5月17日 下午5:14:02
	 */
	public void setnx(String key, String value) {
		Jedis jedis = null;
		try {
			jedis = getTool().getResource();
			jedis.setnx(key, value);
		} catch (Throwable t) {
			logger.error("Jedis setnx(String key, String value) error!", t);
		} finally {
			if(jedis!=null) jedis.close();
		}
	}
	
	/**
	 * @Description: 发布消息
	 * @param channel
	 * @param message
	 * @return void 返回类型
	 * @author gaoxiang
	 * @date 2016年5月17日 下午5:17:07
	 */
	public void publish(String channel, String message) {
		Jedis jedis = null;
		try {
			jedis = getTool().getResource();
			jedis.publish(channel, message);
		} catch (Throwable t) {
			logger.error("Jedis subscribe(String channel, JedisPubSub listener) error!", t);
		} finally {
			if(jedis!=null) jedis.close();
		}
	}
	
	public Map<String, String> pubsubNumSub(String... channels) {
		Jedis jedis = null;
		try {
			jedis = getTool().getResource();
			return jedis.pubsubNumSub(channels);
		} catch (Throwable t) {
			logger.error("Jedis pubsubNumSub(String... channels) error!", t);
		} finally {
			if(jedis!=null) jedis.close();
		}
		return null;
	}
	
	/**
	 * @Description: 订阅消息
	 * @param channel
	 * @param listener
	 * @return void 返回类型
	 * @author gaoxiang
	 * @date 2016年5月17日 下午5:22:13
	 */
	public void subscribe(String channel, JedisPubSub listener) {
		Jedis jedis = null;
		try {
			jedis = getTool().getResource();
			jedis.subscribe(listener, new String[] { channel });
		} catch (Throwable t) {
			logger.error("Jedis subscribe(String channel, JedisPubSub listener) error!", t);
		} finally {
			if(jedis!=null) jedis.close();
		}
	}
	
	/**
	 * @Description: 判断某key是否存在
	 * @param key
	 * @return Boolean 返回类型
	 * @author gaoxiang
	 * @date 2016年5月17日 下午5:25:17
	 */
	public Boolean exists(String key) {
		Jedis jedis = null;
		try {
			jedis = getTool().getResource();
			return jedis.exists(key);
		} catch (Throwable t) {
			logger.error("Jedis subscribe(String channel, JedisPubSub listener) error!", t);
		} finally {
			if(jedis!=null) jedis.close();
		}
		return false;
	}
	
	/**
	 * @Description: 哈希get
	 * @param key
	 * @param field
	 * @return String 返回类型
	 * @author gaoxiang
	 * @date 2016年5月17日 下午5:21:55
	 */
	public String hget(String key, String field) {
		Jedis jedis = null;
		try {
			jedis = getTool().getResource();
			return jedis.hget(key, field);
		} catch (Throwable t) {
			logger.error("Jedis error!", t);
		} finally {
			if(jedis!=null) jedis.close();
		}
		return null;
	}
	
	/**
	 * @Description: 哈希删除
	 * @param key
	 * @param fields
	 * @return void 返回类型
	 * @author gaoxiang
	 * @date 2016年5月17日 下午5:29:28
	 */
	public void hdel(String key,String... fields) {
		Jedis jedis = null;
		try {
			jedis = getTool().getResource();
			jedis.hdel(key,fields);
		} catch (Throwable t) {
			logger.error("Jedis hdel(String key,String... fields) error!", t);
		} finally {
			if(jedis!=null) jedis.close();
		}
	}
	
	/**
	 * @Description: 哈希存储
	 * @param key
	 * @return Map<String,String> 返回类型
	 * @author gaoxiang
	 * @date 2016年5月17日 下午5:29:41
	 */
	public void hset(String key, String field, String value) {
		Jedis jedis = null;
		try {
			jedis = getTool().getResource();
			jedis.hset(key,field,value);
		} catch (Throwable t) {
			logger.error("Jedis hset(String key, String field, String value) error!", t);
		} finally {
			if(jedis!=null) jedis.close();
		}
	}
	
	public Map<String, String> hgetAll(String key) {
		Jedis jedis = null;
		try {
			jedis = getTool().getResource();
			return jedis.hgetAll(key);
		} catch (Throwable t) {
			logger.error("Jedis error!", t);
		} finally {
			if(jedis!=null) jedis.close();
		}
		return null;
	}
	
	/**
	 * @Description: 正则匹配key
	 * @param pattern
	 * @return Set<String> 返回类型
	 * @author gaoxiang
	 * @date 2016年5月17日 下午5:21:12
	 */
	public Set<String> keys(String pattern) {
		Jedis jedis = null;
		try {
			jedis = getTool().getResource();
			return jedis.keys(pattern);
		} catch (Throwable t) {
			logger.error("Jedis error!", t);
		} finally {
			if(jedis!=null) jedis.close();
		}
		return null;
	}
	
	/**
	 * @Description: 设置指定时长的key-value
	 * @param key
	 * @param expireTimes
	 * @return void 返回类型
	 * @author gaoxiang
	 * @date 2016年5月17日 下午5:21:28
	 */
	public void expire(String key, int expireTimes) {
		Jedis jedis = null;
		try {
			jedis = getTool().getResource();
			jedis.expire(key, expireTimes);
		} catch (Throwable t) {
			logger.error("Jedis setExpireTime(String key, int expireTimes) error!", t);
		} finally {
			if(jedis!=null) jedis.close();
		}
	}
	
	/**
	 * @Description: 删除指定键值对
	 * @param key
	 * @return void 返回类型
	 * @author gaoxiang
	 * @date 2016年5月17日 下午5:19:48
	 */
	public void del(String key) {
		Jedis jedis = null;
		try {
			jedis = getTool().getResource();
			jedis.del(key);
		} catch (Throwable t) {
			logger.error("Jedis del(String key) error!", t);
		} finally {
			if(jedis!=null) jedis.close();
		}
	}
	
	public Pool<Jedis> getPool() {
		return pool;
	}
	
	public void setPool(Pool<Jedis> pool) {
		this.pool = pool;
	}
	
	public String getIpAddr() {
		return ipAddr;
	}
	
	public void setIpAddr(String ipAddr) {
		this.ipAddr = ipAddr;
	}
	
	public String getPort() {
		return port;
	}
	
	public void setPort(String port) {
		this.port = port;
	}
	
	public String getPassword() {
		return password;
	}
	
	public void setPassword(String password) {
		this.password = password;
	}
	
	public int getTimeout() {
		return timeout;
	}
	
	public void setTimeout(int timeout) {
		this.timeout = timeout;
	}
	
	public int getMaxIdle() {
		return maxIdle;
	}
	
	public void setMaxIdle(int maxIdle) {
		this.maxIdle = maxIdle;
	}

	
}
